home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992…ugust: Hack to the Future / ADC Developer CD (1992-08) (''Hack To The Future'')_iso / Dev.CD 199208.iso / Technical Documentation / DTS Sample Code / Snippets / Graphics & Printing / Printing / PDlog Expand / PDlog Expand.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-15  |  11.2 KB  |  369 lines  |  [TEXT/KAHL]

  1. /* PDlog Expand.c    Derived from TN #95.
  2.  
  3. Dave Hersey, MacDTS
  4.  
  5. Think C 4.0.4 source.
  6.  
  7.    NOTE: Apple reserves the top half of the screen (where the current DITL
  8.    items are located). Applications may use the bottom half of the screen to
  9.    add items, but should not change any items in the top half of the screen.
  10.    An application should expand the print dialogs only as much as is
  11.    absolutely necessary.
  12. */
  13.  
  14. /*
  15.    Note: A global search and replace of 'Job' with 'Stl' will produce code
  16.    that modifies the style dialogs
  17. */
  18. /*
  19. #include <MacTypes.h>
  20. #include <Quickdraw.h>
  21. #include <ResourceMgr.h>
  22. #include <WindowMgr.h>
  23. #include <pascal.h>
  24. #include <printmgr.h>
  25. #define nil        0L
  26. #define NULL    nil
  27. */
  28. static TPPrDlg PrtJobDialog;        /* pointer to job dialog */
  29.  
  30. /* This points to the following structure:
  31.     
  32. struct { 
  33.         DialogRecord  Dlg;        (The Dialog window)
  34.         ProcPtr       pFltrProc;  (The Filter Proc.)
  35.         ProcPtr       pItemProc;  (The Item evaluating proc - we'll change this)
  36.         THPrint       hPrintUsr;  (The user's print record.)
  37.         Boolean       fDoIt;    
  38.         Boolean       fDone;    
  39.             (Four longs -- reserved by Apple Computer)
  40.         long          lUser1;         
  41.         long          lUser2;        
  42.         long          lUser3;    
  43.         long          lUser4;        
  44. } TPrDlg; *TPPrDlg;          
  45. */
  46.  
  47. /* Declare ‘pascal’ functions and procedures */
  48.  
  49. extern int        Append_DITL(TPPrDlg, int);            /* Our AppendDITL function.            */
  50. extern pascal    TPPrDlg MyJobDlgInit(THPrint);        /* Our extention to PrJobInit.        */
  51. extern pascal    void MyJobItems(TPPrDlg, short);    /* Our modal item handler.            */
  52. extern OSErr    Print(void);
  53.  
  54. #define MyDITL 256  /* resource ID of my DITL to be spliced onto job dialog */
  55.  
  56. THPrint hPrintRec;          /* handle to print record */
  57. long prFirstItem;           /* save our first item here */
  58. long prPItemProc;           /* we need to store the old itemProc here */
  59.  
  60. /*-----------------------------------------------------------------------*/
  61.     WindowPtr   MyWindow;
  62.     OSErr       err;
  63.     Str255      myStr;
  64.  
  65. typedef
  66.     struct dialog_item_struct
  67.     {
  68.         Handle  handle;     /* handle or procedure pointer for this item */
  69.         Rect    bounds;     /* display rectangle for this item */
  70.         char    type;       /* item type - 1 */
  71.         char    data[1];    /* length byte of data */
  72.     }
  73.     DialogItem, *DialogItemPtr, **DialogItemHandle;
  74.  
  75. typedef
  76.     struct append_item_list_struct
  77.     {
  78.         int           max_index; /* number of items - 1 */
  79.         DialogItem    items[1]; /* first item in the array */
  80.     }
  81.     ItemList, *ItemListPtr, **ItemListHandle;
  82.  
  83. typedef
  84.     union signed_byte_union
  85.     {
  86.         int        integer;
  87.         char    bytes[2];
  88.     }
  89.     ByteAccess;
  90.  
  91.  
  92. /*    This routine appends all of the items of a specified DITL    */
  93. /*    onto the end of a specified DLOG — We don’t even need to know the format    */
  94. /*    of the DLOG    */
  95.  
  96. /*    this will be done in 3 steps:    */
  97. /*     1. append the items of the specified DITL onto the existing DLOG    */
  98. /*     2. expand the original dialog window as required    */
  99. /*     3. return the adjusted number of the first new user item    */
  100.  
  101.  
  102. int Append_DITL(TPPrDlg dialog, int item_list_ID)
  103. {
  104.     Point             offset;
  105.     Rect            max_rect;
  106.     ItemListHandle     append_item_list;    /* handle to DITL being appended */
  107.     DialogItemPtr     item;                /* pointer to item being appended */
  108.     ItemListHandle    dlg_item_list;        /* handle to DLOG's item list */
  109.     int               first_item;
  110.     int                new_items, data_size, i;
  111.     ByteAccess        usb;
  112.     OSErr              err;
  113.  
  114. /*
  115.     Using the original DLOG
  116.  
  117.     1. Remember the original window Size.
  118.     2. Set the offset Point to be the bottom of the original window.
  119.     3. Subtract 5 pixels from bottom and right, to be added
  120.        back later after we have possibly expanded window.
  121.     4. Get working Handle to original item list.
  122.     5. Calculate our first item number to be returned to caller.
  123.     6. Get locked Handle to DITL to be appended.
  124.     7. Calculate count of new items.
  125. */
  126.  
  127.     if (dialog == NULL) ExitToShell();
  128.  
  129.     max_rect = ((DialogPeek)dialog)->window.port.portRect;
  130.     offset.v = max_rect.bottom;
  131.     offset.h = 0;
  132.     max_rect.bottom -= 5;
  133.     max_rect.right -= 5;
  134.  
  135.     dlg_item_list = (ItemListHandle)((DialogPeek)dialog)->items;
  136.     first_item = (**dlg_item_list).max_index + 2;
  137.  
  138.     append_item_list = (ItemListHandle)GetResource('DITL', item_list_ID);
  139.     if ( append_item_list == NULL )
  140.         return first_item;
  141.  
  142.     HLock((Handle)append_item_list);
  143.     new_items = (**append_item_list).max_index + 1;
  144.  
  145. /*
  146.      For each item,
  147.       1. Offset the rectangle to follow the original window.
  148.       2. Make the original window larger if necessary.
  149.       3. fill in item handle according to type.
  150. */
  151.  
  152.     item = (**append_item_list).items;
  153.     for ( i = 0; i < new_items; i++ )
  154.     {
  155.         OffsetRect(&item->bounds, offset.h, offset.v);
  156.         UnionRect(&item->bounds, &max_rect, &max_rect);
  157.         usb.integer = 0;
  158.         usb.bytes[1] = item->data[0];
  159.  
  160.         switch ( item->type & 0x7F )
  161.         {
  162.             case ctrlItem + btnCtrl :
  163.             case ctrlItem + chkCtrl :
  164.             case ctrlItem + radCtrl :
  165.                 item->handle = (Handle)NewControl((DialogPtr) dialog,
  166.                                                   &item->bounds,
  167.                                                   (StringPtr)item->data,
  168.                                                   TRUE,
  169.                                                   0, 0, 1,
  170.                                                   item->type & 0x03,
  171.                                                   0);
  172.             break;
  173.  
  174.             case ctrlItem + resCtrl :
  175.             {
  176.                 item->handle = (Handle)GetNewControl(*(int*)(item->data + 1), (DialogPtr) dialog);
  177.                 (**(ControlHandle)item->handle).contrlRect = item->bounds;
  178.             }
  179.             break;
  180.  
  181.             case statText :
  182.             case editText :
  183.                 err = PtrToHand(item->data + 1, &item->handle, usb.integer);
  184.             break;
  185.  
  186.             case iconItem :
  187.                 item->handle = GetIcon(*(int*)(item->data + 1));
  188.             break;
  189.  
  190.             case picItem :
  191.                 item->handle = (Handle)GetPicture(*(int*)(item->data + 1));
  192.             break;
  193.  
  194.             default :
  195.                 item->handle = NULL;
  196.         }
  197.  
  198.         data_size = (usb.integer + 1) & 0xFFFE;
  199.         item = (DialogItemPtr)((char*)item + data_size + sizeof(DialogItem));
  200.     }
  201.  
  202.     err = PtrAndHand((**append_item_list).items,
  203.                      (Handle)dlg_item_list,
  204.                      GetHandleSize((Handle) append_item_list));
  205.     (**dlg_item_list).max_index += new_items;
  206.     HUnlock((Handle) append_item_list);
  207.     ReleaseResource((Handle) append_item_list);
  208.  
  209.     max_rect.bottom += 5;
  210.     max_rect.right += 5;
  211.     SizeWindow((WindowPtr) dialog, max_rect.right, max_rect.bottom, TRUE);
  212.  
  213.     return first_item;
  214. }
  215.  
  216.  
  217. /*------------------------------------------------------------------------*/
  218.  
  219. OSErr Print()
  220. {
  221.     /* call PrJobInit to get pointer to the invisible job dialog */
  222.     hPrintRec = (THPrint)(NewHandle(sizeof(TPrint)));
  223.     PrintDefault(hPrintRec);
  224.     PrValidate(hPrintRec);
  225.     if (PrError() != noErr)
  226.         return PrError();        
  227.  
  228.     PrtJobDialog = PrJobInit(hPrintRec);
  229.     if (PrError() != noErr)
  230.         return PrError();        
  231.  
  232.     
  233.     if (!PrDlgMain(hPrintRec, (ProcPtr) &MyJobDlgInit)) /* this line does all the stuff */
  234.         return iPrAbort;
  235.  
  236.     if (PrError() != noErr)
  237.         return PrError();        
  238.     
  239. /* that's all for now */
  240.         
  241. } /* Print */
  242.  
  243. /*------------------------------------------------------------------------*/
  244.  
  245. pascal TPPrDlg MyJobDlgInit (hPrint)
  246. THPrint hPrint;
  247. /*
  248.    this routine appends items to the standard job dialog and sets up the
  249.    user fields of the printing dialog record TPRDlg
  250.  
  251.    This routine will be called by PrDlgMain
  252. */
  253.  
  254. {
  255.     short      firstItem;    /* first new item number */
  256.     
  257.     short      itemType, item;
  258.     Handle     itemH;
  259.     Rect       itemBox;
  260.     
  261.     firstItem = Append_DITL(PrtJobDialog, MyDITL); /*call routine to do this */
  262.     
  263.     prFirstItem = firstItem; /* save this so MyJobItems can find it */
  264.  
  265. /* now we'll set up our DITL items -- The radio buttons */
  266.     
  267.     for (item = 5; item <= 7; item++)
  268.     {
  269.         GetDItem((DialogPtr) PrtJobDialog,firstItem + item -1,&itemType,&itemH,&itemBox);
  270.         SetCtlValue((ControlHandle) itemH, (item == 5));
  271.     }
  272.     
  273. /* now we'll set up the second of our DITL items  -- The checkbox */
  274.  
  275.     GetDItem((DialogPtr) PrtJobDialog,firstItem +2,&itemType,&itemH,&itemBox);
  276.     SetCtlValue((ControlHandle) itemH,1);
  277.  
  278. /*
  279.    Now comes the part where we patch in our item handler.  We have to save
  280.    the old item handler address, so we can call it if one of the standard
  281.    items is hit, and put our item handler's address in pItemProc field of
  282.    the TPrDlg struct
  283. */
  284.  
  285.     prPItemProc = (long)PrtJobDialog->pItemProc;
  286.     
  287. /* Now we'll tell the modal item handler where our routine is */
  288.     PrtJobDialog->pItemProc = (ProcPtr)&MyJobItems;
  289.     
  290.  
  291. /* PrDlgMain expects a pointer to the modified dialog to be returned...*/
  292.     return PrtJobDialog;
  293.     
  294. } /*myJobDlgInit*/
  295.  
  296. /*-----------------------------------------------------------------------*/
  297.  
  298. /* here's the analogue to the SF dialog hook */
  299.  
  300. pascal void MyJobItems(theDialog,itemNo)
  301. TPPrDlg     theDialog;
  302. short       itemNo;
  303.  
  304. { /* MyJobItems */
  305.     short   myItem;
  306.     short   firstItem, item, itemType, theValue;
  307.     Handle  itemH;
  308.     Rect    itemBox;
  309.     
  310.     firstItem = prFirstItem;      /* remember, we saved this in myJobDlgInit */
  311.     myItem = itemNo-firstItem+1;  /* "localize" current item No */
  312.     if (myItem > 0)               /* if localized item > 0, it's one of ours */
  313.     {
  314.         /* find out which of our items was hit */
  315.  
  316.         switch (myItem)
  317.         {
  318.             case 1:            /*    Static text.    */
  319.                 break;
  320.             case 2:            /*    Edit text.        */
  321.                 break;
  322.             case 3:            /*    Check box.        */
  323.                        GetDItem((DialogPtr) theDialog,firstItem +2,&itemType,&itemH,&itemBox);
  324.                      theValue = GetCtlValue((ControlHandle) itemH);
  325.                      SetCtlValue((ControlHandle) itemH, theValue != 1);
  326.                 break;
  327.             case 4:            /*    Push button.    */
  328.                 break;
  329.             case 5:            /*    Radio buttons    */
  330.             case 6:
  331.             case 7:
  332.                    for (item = 5; item <= 7; item++)
  333.                    {
  334.                        GetDItem((DialogPtr) theDialog,firstItem +item -1,&itemType,&itemH,&itemBox);
  335.                      SetCtlValue((ControlHandle) itemH, item == myItem);
  336.                    }
  337.                 break;
  338.             case 8:            /*    Edit text.        */
  339.                 break;
  340.             default: Debugger(); /* OH OH */    
  341.         } /* switch */
  342.     } /* if (myItem > 0) */
  343.     else /* chain to standard item handler, whose address is saved in 
  344.               prPItemProc */
  345.     {
  346.         CallPascal(theDialog,itemNo,prPItemProc);
  347.     }
  348. } /* MyJobItems */
  349.  
  350.  
  351. main()
  352. {    
  353.     Rect        myWRect;
  354.     
  355.     InitGraf(&thePort);
  356.     InitFonts();
  357.     InitWindows();
  358.     InitMenus();
  359.     InitDialogs(nil);
  360.     InitCursor();
  361.     SetRect(&myWRect,50,260,350,340);
  362.     
  363.     /* call the routine that does printing */
  364.     PrOpen();
  365.     err = Print();
  366.     
  367.     PrClose();
  368. } /* main */
  369.